﻿// ------------------------------------------------------------------------------------------------
//  <copyright file="Cache.cs" company="Iveely">
//    Copyright (c) Iveely Liu.  All rights reserved.
//  </copyright>
//  
//  <Create Time>
//    03/02/2013 21:59 
//  </Create Time>
//  
//  <contact owner>
//    liufanping@iveely.com 
//  </contact owner>
//  -----------------------------------------------------------------------------------------------

#region

using System;
using IveelySE.Common.Log;
using IveelySE.NLP.Common.DataStructure.Table;

#endregion

namespace IveelySE.Index
{
    /// <summary>
    ///   缓存队列
    /// </summary>
    public static class Cache
    {
        /// <summary>
        ///   记录缓存时间
        /// </summary>
        private static DateTime _bakUptime = DateTime.Now;

        /// <summary>
        ///   哈希链表
        /// </summary>
        private static readonly HashLinkTable LinkTable = new HashLinkTable();

        /// <summary>
        ///   加入缓存队列
        /// </summary>
        /// <param name="key"> 用户搜索关键字 </param>
        /// <param name="result"> 用户关键字对应的结果 </param>
        public static void Join(object key, object result)
        {
            LinkTable.Add(key, result);
        }

        /// <summary>
        ///   搜索匹配
        /// </summary>
        /// <param name="key"> 用户搜索的关键字 </param>
        /// <returns> 返回缓存中的结果 </returns>
        public static string Match(string key)
        {
            //每十分钟情况一次缓存
            if((DateTime.Now - _bakUptime).TotalMinutes > 10)
            {
                Clean();
                _bakUptime = DateTime.Now;
            }
            return LinkTable.FindValue(key).ToString();
        }

        /// <summary>
        ///   清楚搜索缓存
        /// </summary>
        public static bool Clean()
        {
            try
            {
                LinkTable.Clean();
            }
            catch(Exception exception)
            {
                //如果无法清除缓存，那么缓存将会失效
                Content.GetInstance().Write(exception.Message, MessageType.Warning);
                return false;
            }
            return true;
        }
    }
}

/*
 *  IveelySE此时的缓存策略相对简单：将用户搜索的结果，按照时间顺序存入内存中，如果已经在内存中，那么将其提升到最近使用范围内，直到内存中的缓存数量（自定义）达到饱和后，
 *  依次淘汰最久未使用的搜索结果。思路相对简单，但是这样的数据结构，我们有一个要求，因为在插入缓存和提取缓存上我们要求时间复杂度为0(1)，要实现这个有一定的难度，HashTable
 *  可以实现插入和查找的效率在0(1),但是此时出现了一个问题，我们对关键字的最近最少使用就出现了问题，它不能准确的定位哪一个关键字在另外一个关键字的之前被搜索，以帮助我们记
 *  录谁先进入缓存中，而且缓存中内部又是不断变化的。举例说明：
       第一时间，搜索关键字“Iveely 1”，那么将记录<Iveely 1,"搜索结果">
       第二时间，搜索关键字“Iveely 2”，那么将记录<Iveely 2,"搜索结果">
       ... ...
       第i时间，搜索关键字“Iveely i”，那么将记录<Iveely i,"搜索结果">
       ... ...
       第N时间，搜索关键字“Iveely N”，那么将记录<Iveely N,"搜索结果">
       此时此刻，当搜索"Iveely 2"的时候，Hashtable都能为我们提供O(1)的插入缓存和从缓存中提取的效率。但是N已经是我们设定的缓存最大数量了（缓存过大会会占用过多内存，影响
 * 程序性能），当我搜索“Iveely N+1” 的时候就糟糕了，由于在缓存中不能找到，那么搜索引擎将从数据库（或分布式文件系统中）提取搜索“Iveely N+1”的结果，然后需要存入缓存，那么
 * 如何替换缓存呢？此时，Hashtable就不能为我们做出判断，此时就是我们的双向链表给我们判断，处于双向链表末尾的需要删除，然后将“Iveely N+1” 的搜索结果存入缓存，标记为双向
 * 链表的表头的next。
 */